package org.lisy.java.collection;

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.collections4.Bag;
import org.apache.commons.collections4.BidiMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.IterableMap;
import org.apache.commons.collections4.MapIterator;
import org.apache.commons.collections4.OrderedMap;
import org.apache.commons.collections4.bag.HashBag;
import org.apache.commons.collections4.bidimap.TreeBidiMap;
import org.apache.commons.collections4.map.HashedMap;
import org.apache.commons.collections4.map.LinkedMap;

/**
 * 集合工具类使用
 * 
 * @author lisy
 */
public class CommonsOperate {

	/**
	 * Commons Collections 增强了 Java Collections Framework，使收集处理变得容易。主要功能: 
	 *   Bag: Bag 界面简化了每个对象具有多个副本的集合
	 *   BidiMap: BidiMap 接口提供双向映射，可用于使用值使用键或键查找值
	 *   MapIterator: MapIterator 接口提供简单而容易的迭代迭代
	 *   Transforming Decorators: 转换装饰器可以在将集合添加到集合时更改集合的每个对象
	 *   Composite Collections: 在需要统一处理多个集合的情况下使用复合集合
	 *   Ordered Map: 有序地图保留添加元素的顺序
	 *   Ordered Set: 有序集保留了添加元素的顺序
	 *   Reference map: 参考图允许在密切控制下对键/值进行垃圾收集
	 *   Comparator implementations: 可以使用许多 Comparator 实现
	 *   Iterator implementations: 许多 Iterator 实现都可用
	 *   Adapter Classes: 适配器类可用于将数组和枚举转换为集合
	 *   Utilities: 实用程序可用于测试测试或创建集合的典型集合论属性，例如 union，intersection。支持关闭
	 */
	
	public static void main(String[] args) {
		
		// Bag 定义了一个集合，用于计算对象在集合中出现的次数
		bagCommons();
		
		// 使用双向映射，可以使用值查找键，并且可以使用键轻松查找值
		BidiMapCommons();
		
		// JDK Map 接口很难迭代，因为迭代要在 EntrySet 或 KeySet 对象上完成。MapIterator 提供了对 Map 的简单迭代
		mapIteratorCommons();
		
		// 地图的新接口，用于保留添加元素的顺序。LinkedMap 和 ListOrderedMap 是两个可用的实现
		// 此接口支持 Map 的迭代器，并允许在 Map 中向前或向后迭代两个方向
		orderedMapCommons();
		
		// CollectionUtils 类库，这个库在 jdk 8 之前非常有用，因为 Java 8 的 Stream API 现在提供了类似的功能
		utilCommons();
	}

	private static void bagCommons() {
		Bag<String> bag = new HashBag<String>(); 
		bag.add("a", 2);
		bag.add("b");
		bag.add("c");
		bag.add("d", 3);
		System.out.println("d is present " + bag.getCount("d") + " times.");
		System.out.println("bag: " +bag);
		System.out.println("Unique Set: " +bag.uniqueSet());
		
		bag.add("c");
		bag.remove("d",2);
		System.out.println("d is present " + bag.getCount("d") + " times.");
		System.out.println("bag: " +bag);
		System.out.println("Unique Set: " +bag.uniqueSet());
		System.out.println();
	}
	
	private static void BidiMapCommons() {
		BidiMap<String, String> bidi = new TreeBidiMap<String, String>(); 
		bidi.put("One", "1");
		bidi.put("Two", "2");
		bidi.put("Three", "3");
		System.out.println(bidi.get("One"));
		System.out.println(bidi.getKey("1"));
		System.out.println("Original Map: " + bidi);
		
		bidi.removeValue("1");
		bidi.put("Two", "二");
		bidi.put("三", "3");
		System.out.println("Modified Map: " + bidi);
		
		BidiMap<String, String> inversedMap = bidi.inverseBidiMap();
		System.out.println("Inversed Map: " + inversedMap);
		System.out.println();
	}
	

	private static void mapIteratorCommons() {
		IterableMap<String, String> map = new HashedMap<String, String>(); 
		map.put("1", "One");
		map.put("2", "Two");
		map.put("3", "Three");
		map.put("4", "Four");
		map.put("5", "Five");
		
		MapIterator<String, String> iterator = map.mapIterator();
		while (iterator.hasNext()) {
			Object key = iterator.next();
			Object value = iterator.getValue();
			System.out.println("key: " + key + " Value: " + value);
			iterator.setValue(value + "_");
		}
		System.out.println(map);
		System.out.println();
	}
	
	private static void orderedMapCommons() {
		OrderedMap<String, String> map = new LinkedMap<String, String>();
		map.put("One", "1");
		map.put("Two", "2");
		map.put("Three", "3");
		System.out.println(map.firstKey());
		System.out.println(map.nextKey("One"));
		System.out.println(map.nextKey("Two"));
		System.out.println();
	}
	
	private static void utilCommons() {
		// Ignore NULL
		List<String> list = new LinkedList<String>(); 
		CollectionUtils.addIgnoreNull(list, null); 
		CollectionUtils.addIgnoreNull(list, "a"); 
		System.out.println(list); 
		if(list.contains(null)) { 
			System.out.println("Null value is present"); 
		} else { 
			System.out.println("Null value is not present"); 
		}
		System.out.println();
		
		// Merge & Sort
		List<String> sortedList1 = Arrays.asList("A","C","E"); 
		List<String> sortedList2 = Arrays.asList("B","D","F"); 
		List<String> mergedList = CollectionUtils.collate(sortedList1, sortedList2);
		System.out.println(mergedList);
		System.out.println();
		
		// 安全空检查(Safe Empty Checks)
		List<String> null_list = null;
		System.out.println("Non-Empty List Check: " + CollectionUtils.isNotEmpty(null_list));
		System.out.println("Empty List Check: " + CollectionUtils.isEmpty(null_list));
		System.out.println();
		
		List<String> list1 = Arrays.asList("A","A","A","C","B","B");
		List<String> list2 = Arrays.asList("A","A","B","B");
		System.out.println("List 1: " + list1); 
		System.out.println("List 2: " + list2);
		// 检查列表是否是另一个列表的一部分
		boolean subCollection = CollectionUtils.isSubCollection(list2, list1);
		System.out.println("Is List 2 contained in List 1: " + subCollection);
		// 获取两个集合（交集）之间的公共对象
		Collection<String> intersection = CollectionUtils.intersection(list1, list2);
		System.out.println("Commons Objects of List 1 and List 2: " + intersection);
		// 通过从其他集合中减去一个集合的对象来获取新集合
		Collection<String> subtract = CollectionUtils.subtract(list1, list2);
		System.out.println("List 1 - List 2: " + subtract);
		// 获取两个集合的并集
		 Collection<String> union = CollectionUtils.union(list1, list2);
		System.out.println("Union of List 1 and List 2: " + union);
		System.out.println();
	}
}
